﻿using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Phone.Controls;
using WindowsPhoneEssentials.Helpers;

namespace WindowsPhoneMVC.Phone
{
    public static class Restore
    {
        #region public attached bool Pivot.PivotPosition
        public static DependencyProperty PivotPositionProperty = DependencyProperty.RegisterAttached("PivotPosition", typeof(bool), typeof(Restore), new PropertyMetadata(PivotPositionChanged));

        public static bool GetPivotPosition(Pivot element)
        {
            return (bool)element.GetValue(PivotPositionProperty);
        }

        public static void SetPivotPosition(Pivot element, object value)
        {
            element.SetValue(PivotPositionProperty, value);
        }
        #endregion

        #region public attached bool Panorama.PanoramaPosition
        public static readonly DependencyProperty PanoramaPositionProperty =
            DependencyProperty.RegisterAttached("PanoramaPosition", typeof (bool), typeof (Restore), new PropertyMetadata(PanoramaPositionChanged));

        public static void SetPanoramaPosition(Panorama element, bool value)
        {
            element.SetValue(PanoramaPositionProperty, value);
        }

        public static bool GetPanoramaPosition(Panorama element)
        {
            return (bool)element.GetValue(PanoramaPositionProperty);
        }
        #endregion

        private static void PivotPositionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var pivot = (Pivot)d;

            pivot.Loaded += PivotLoaded;
            pivot.SelectionChanged += PivotSelectionChanged;
        }

        private static void PanoramaPositionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var panorama = (Panorama) d;

            panorama.Loaded += PanoramaLoaded;
            panorama.SelectionChanged += PanoramaSelectionChanged;
        }

        static void PivotLoaded(object sender, RoutedEventArgs e)
        {
            var pivot = (Pivot)sender;
            var viewModel = GetViewModel(pivot);
            if (viewModel == null) return;

            var transientProperty = viewModel.PageState.Load<TransientProperty>("PivotPosition");
            var lastPosition = transientProperty == null ? null : (int?)transientProperty.Value;
            if (lastPosition != null && lastPosition.Value != -1 && lastPosition.Value < pivot.Items.Count)
            {
                pivot.SelectedItem = pivot.Items[lastPosition.Value];
            }
        }

        static void PivotSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var pivot = (Pivot)sender;
            var viewModel = GetViewModel(pivot);
            if (viewModel != null)
            {
                viewModel.PageState.Save("PivotPosition", new TransientProperty { Value = pivot.SelectedIndex });
            }
        }

        static void PanoramaLoaded(object sender, RoutedEventArgs e)
        {
            var panorama = (Panorama)sender;
            var viewModel = GetViewModel(panorama);
            if (viewModel == null) return;

            var transientProperty = viewModel.PageState.Load<TransientProperty>("PanoramaPosition");
            var lastPosition = transientProperty == null ? null : (int?)transientProperty.Value;
            if (lastPosition != null && lastPosition.Value != -1 && lastPosition.Value < panorama.Items.Count)
            {
                panorama.DefaultItem = panorama.Items[lastPosition.Value];
            }
        }

        static void PanoramaSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var panorama = (Panorama)sender;
            var viewModel = GetViewModel(panorama);
            if (viewModel != null)
            {
                viewModel.PageState.Save("PanoramaPosition", new TransientProperty { Value = panorama.SelectedIndex });
            }
        }

        private static ViewModelBase GetViewModel(DependencyObject d)
        {
            var viewModel = d.AncestorsAndSelf()
                .OfType<FrameworkElement>()
                .Select(a => a.DataContext)
                .OfType<ViewModelBase>()
                .FirstOrDefault();

            //Cant find any element in visual tree with viewmodel of ViewModelBase
            if (viewModel == null)
            {
                Debug.WriteLine("Cannot find a DataContext of type ViewModelBase in visual tree to Restore Panorama position");
                return null;
            }
            return viewModel;
        }
    }
}